//==== Screwd430

/* Pins:
 P1.0  - Motor (1- On, 0- Off)
 P1.1, P1.2 - UART
 P1.3  - Motor button
 P1.4  - ADC accu
 P1.5  - ADC input
 P1.6  - Charger On
 P1.7  - Button Check
 P2.3  - LED Yellow
 P2.4  - LED Red
 P2.5  - LED Green

  CompA - checks input power for charge, P1.4
    Until 5V on input - Use LPM0 and indicate charging
    If no power  - LPM4

*/

#include "io430.h"

#define _BIS_SR(X) __bis_SR_register(X)

#define BTN1 0x08
#define BTN2 0x80
#define MOTOR 0x01
#define CHARGE 0x40

enum eState {
  SLEEP = 0,
  CHARGING = 1,
  BATT_FULL = 2,
  MEASURE = 4,
  SCREW_ON = 8
};

enum eRequest {
  NO_REQ = 0,
  REQ_ADC_SAMPLE,
  REQ_BUTTONS,
  REQ_TIMER,
  REQ_COMPARATOR
};

enum eState myState;
enum eRequest wakeUpReq;

void hw_init()
{
  // DCO
  BCSCTL1 = CALBC1_1MHZ;    
  DCOCTL = CALDCO_1MHZ;

  // Ports
  P1DIR |= MOTOR|CHARGE; 
  P1REN |= BTN1|BTN2;    // button pull-ups
  P1OUT |= BTN1|BTN2;
  P1OUT &= ~(MOTOR|CHARGE);
  P2DIR |= 0x38;

  // UART at 9600
  //   Baud rate divider with 1MHz = 1MHz/9600 = ~104
  P1SEL = BIT1 + BIT2;                  // P1.1 = RXD, P1.2=TXD
  P1SEL2 = BIT1 + BIT2;  
  
  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
  UCA0BR0 = 104;                            // 1MHz 9600
  UCA0BR1 = 0;                              // 1MHz 9600
  UCA0MCTL = UCBRS2 + UCBRS0;               // Modulation UCBRSx = 5
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
  
  // Button interrupts
  P1IE |= BTN1|BTN2;                             // P1.7 & P1.3 interrupt enabled
  P1IES |= BTN1|BTN2;                            // P1.7 & P1.3 Hi/lo edge
  P1IFG &= ~(BTN1|BTN2);                           // P1.7 & P1.3 IFG cleared
  
  // Timer
  TACTL = TASSEL_2 + MC_2 + TAIE;
  
  // Comp A+
  CACTL2 = P2CA3 + CAF;
  CACTL1 = CAREF_2 + CAIE + CAON;
     
  // ADC
  ADC10CTL1 = INCH_10 + CONSEQ_1;            // Thermo+all inputs, TMR0, multi-ch single sequence
  ADC10CTL0 = ADC10SHT_2 + MSC + ADC10ON + ADC10IE;
  ADC10DTC1 = 0x06;                         // 6 conversions
  ADC10AE0 |= 0x30;                         // P1.5,4 ADC10 option select
}

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
  myState = CHARGING; //SLEEP;
  wakeUpReq = NO_REQ;
  
  hw_init();

  P1OUT |= 0x40;
       
  while (1) {
    
    switch (wakeUpReq) {
    case REQ_TIMER:
      ADC10CTL0 &= ~ENC;
      while (ADC10CTL1 & BUSY);               // Wait if ADC10 core is active
      ADC10SA = 0x200;                        // Data buffer start
      ADC10CTL0 |= ENC + ADC10SC; 
      break;
    default:
      break;
    }
    wakeUpReq = NO_REQ;
    if(myState==SLEEP) {
      //_BIS_SR(LPM4_bits + GIE);                 // Enter LPM4 w/interrupt
      // set all to sleep position
    } else {
      _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/interrupt
    }
  }
}


// Port 1 interrupt service routine - read buttons
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
  /*
  if ((P1IN&BTN1) != 0) {
    //P2OUT |= 0x10;
    //P1IES |= BTN1;
  } else {
    //P1IES &= ~BTN1;
  }
  
  if ((P1IN&BTN2) != 0) {
    //P2OUT |= 0x20;
    //P1IES |= BTN2;
  } else {
    //P1IES &= ~BTN2;
  }*/
  
  P1IFG &= ~0x88;                           // IFG cleared
  __bic_SR_register_on_exit(CPUOFF);
}

// Echo back RXed character, confirm TX buffer is ready first
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
  while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
  //UCA0TXBUF = UCA0RXBUF;                    // TX -> RXed character
  UCA0TXBUF = myState+0x30;
  P2OUT ^= 0x08;                            // RED toggle
}

// Comparator interrupt
#pragma vector=COMPARATORA_VECTOR
__interrupt void COMPARATORA_ISR(void)
{
  //myState = CHARGING;
  P2OUT ^= 0x20;   
  __bic_SR_register_on_exit(CPUOFF);
}

// ADC10 interrupt service routine
// Wake Up from sleep after conversion
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
  P1OUT &= ~0x40;
  __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
}

// Timer_A3 Interrupt Vector (TA0IV) handler
// Starts ADC conversion
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{
 switch( TA0IV )
 {
   case  2: break;                          // CCR1 not used
   case  4: break;                          // CCR2 not used
   case 10: 
     
     P1OUT ^= 0x01;                  // overflow
     if (CACTL2 & CAOUT)
       P2OUT |= 0x10;
     else
       P2OUT &= ~0x10;
     break;
  }
       wakeUpReq = REQ_TIMER;
     __bic_SR_register_on_exit(CPUOFF);

}

